package day24.test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 斗地主扑克牌游戏类
 * 实现扑克牌的生成、洗牌、发牌和排序功能
 * 
 * 扑克牌说明:
 * - 54张牌: 13个点数(2,3,4,5,6,7,8,9,10,J,Q,K,A) * 4种花色(黑桃,红桃,梅花,方块) + 大小王
 * - 牌的大小顺序: 3 < 4 < 5 < 6 < 7 < 8 < 9 < 10 < J < Q < K < A < 2 < 小王 < 大王
 */
public class DouDiZhu {
    // 花色数组，包含四种花色：黑桃(♠)、红桃(♥)、梅花(♣)、方块(♦)
    private static final String[] colors = {"♠", "♥", "♣", "♦"};
    
    // 点数数组，按照斗地主规则排列（3最小，2最大）
    private static final String[] RANKS = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};
    
    // 存储所有扑克牌的列表，用于洗牌和发牌
    private List<String> deck;
    
    // 三名玩家的手牌列表
    private List<String> player1;
    private List<String> player2;
    private List<String> player3;
    
    // 底牌列表，斗地主中最后三张牌作为底牌
    private List<String> dipai;
    
    // 牌的权重映射，用于排序时比较牌的大小
    private Map<String, Integer> cardWeights;
    
    /**
     * 构造函数，初始化游戏所需的各个数据结构
     */
    public DouDiZhu() {
        deck = new ArrayList<>();
        player1 = new ArrayList<>();
        player2 = new ArrayList<>();
        player3 = new ArrayList<>();
        dipai = new ArrayList<>();
        cardWeights = new HashMap<>();
        initializeCardWeights();
    }

    /**
     * 初始化牌的权重映射表
     * 根据斗地主规则设置每张牌的权重，用于后续排序比较
     * 3权重为0（最小），4为1，...，2为12，小王为13，大王为14（最大）
     */
    private void initializeCardWeights() {
        // 设置点数3最小，2最大，按斗地主规则依次递增
        for (int i = 0; i < RANKS.length; i++) {
            cardWeights.put(RANKS[i], i);
        }
        
        // 特殊牌权重设置：小王权重为13，大王权重为14
        cardWeights.put("小王", 13); 
        cardWeights.put("大王", 14);  
    }
    
    /**
     * 生成54张完整的扑克牌
     * 包括：13个点数 × 4种花色 + 大小王
     */
    public void generateCards() {
        // 清空牌堆，确保每次生成都是全新的牌组
        deck.clear();
        
        // 生成普通牌 (13个点数 * 4种花色)
        for (String rank : RANKS) {
            for (String suit : colors) {
                // 组合花色和点数，如"♠3"、"♥A"等
                deck.add(suit + rank);
            }
        }
        
        // 添加大小王到牌堆中
        deck.add("小王"); 
        deck.add("大王"); 
    }
    
    /**
     * 洗牌方法
     * 使用Collections.shuffle()方法随机打乱牌堆顺序
     */
    public void shuffleCards() {
        Collections.shuffle(deck);
    }
    
    /**
     * 发牌方法
     * 按照斗地主规则：三名玩家轮流摸牌，每人17张，剩余3张作为底牌
     */
    public void dealCards() {
        // 清空玩家手牌和底牌，确保每次发牌都是新的开始
        player1.clear();
        player2.clear();
        player3.clear();
        dipai.clear();
        
        // 发牌：每人17张牌，总共51张
        // 采用轮流发牌方式：第一张给玩家1，第二张给玩家2，第三张给玩家3，第四张再给玩家1...
        for (int i = 0; i < 51; i++) {
            String card = deck.get(i);
            switch (i % 3) {
                case 0:
                    player1.add(card);
                    break;
                case 1:
                    player2.add(card);
                    break;
                case 2:
                    player3.add(card);
                    break;
            }
        }
        
        // 剩余3张作为底牌（斗地主规则）
        for (int i = 51; i < 54; i++) {
            dipai.add(deck.get(i));
        }
    }
    
    /**
     * 按牌的大小顺序排序所有玩家的手牌和底牌
     * 根据initializeCardWeights()中定义的权重进行排序
     */
    public void sortCards() {
        // 使用Lambda表达式和自定义比较器对玩家1的手牌进行排序
        Collections.sort(player1, (card1, card2) -> {
            // 提取牌的点数部分进行比较
            String rank1 = getRankFromCard(card1);
            String rank2 = getRankFromCard(card2);
            
            // 根据权重映射表比较两张牌的大小
            return cardWeights.get(rank1).compareTo(cardWeights.get(rank2));
        });
        
        // 对玩家2的手牌进行排序
        Collections.sort(player2, (card1, card2) -> {
            String rank1 = getRankFromCard(card1);
            String rank2 = getRankFromCard(card2);
            
            return cardWeights.get(rank1).compareTo(cardWeights.get(rank2));
        });
        
        // 对玩家3的手牌进行排序
        Collections.sort(player3, (card1, card2) -> {
            String rank1 = getRankFromCard(card1);
            String rank2 = getRankFromCard(card2);
            
            return cardWeights.get(rank1).compareTo(cardWeights.get(rank2));
        });
        
        // 对底牌进行排序
        Collections.sort(dipai, (card1, card2) -> {
            String rank1 = getRankFromCard(card1);
            String rank2 = getRankFromCard(card2);
            
            return cardWeights.get(rank1).compareTo(cardWeights.get(rank2));
        });
    }
    
    /**
     * 从牌中提取点数
     * @param card 牌面字符串，如"♠3"、"♥A"、"小王"等
     * @return 点数字符串，如"3"、"A"、"小王"等
     */
    private String getRankFromCard(String card) {
        // 特殊处理大小王
        if (card.equals("小王") || card.equals("大王")) {
            return card;
        }
        
        // 去掉花色，返回点数部分（从索引1开始截取到末尾）
        // 例如："♠3" -> "3"，"♥A" -> "A"
        return card.substring(1);
    }
    
    /**
     * 显示玩家手牌和底牌
     * 用于调试或展示游戏状态
     */
    public void showCards() {
        System.out.println("\n玩家1的手牌:");
        System.out.println(player1);

        System.out.println("\n玩家2的手牌:");
        System.out.println(player2);

        System.out.println("\n玩家3的手牌:");
        System.out.println(player3);

        System.out.println("\n底牌:");
        System.out.println(dipai);
    }
}